﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ContestMeter.Common;
using System.Windows.Input;
using Microsoft.Practices.Unity;
using System.IO;
using System.Collections.ObjectModel;
using System.Windows.Forms;
using ContestMeter.UI;
using ContestMeter.Teacher.UI.Properties;

namespace ContestMeter.Teacher.UI
{
    public class BatchCheckerViewModel : ViewModel<MainView>
    {
        public BatchCheckerViewModel(IUnityContainer container, MainView view)
            : base(container, view, false)
        {
        }

        /// <summary>
        /// Может существовать только в несобственном варианте
        /// </summary>
        private BatchCheckerViewModel() { }

        const string FolderPropertyName = "Folder";
        private string _folder;
        public string Folder
        {
            get { return _folder; }
            set
            {
                if (_folder != value)
                {
                    _folder = value;
                    OnPropertyChanged(FolderPropertyName);
                    RunCanExecuteChanged();
                }
            }
        }

        #region Run Command
        private DelegateCommand<object> _runCommand;
        public ICommand RunCommand
        {
            get
            {
                if (_runCommand == null)
                {
                    _runCommand = new DelegateCommand<object>(x => BeginRun(), x => CanRun());
                }
                return _runCommand;
            }
        }
        protected virtual void RunCanExecuteChanged()
        {
            if (_runCommand != null)
            {
                _runCommand.RaiseCanExecuteChanged();
            }
        }
        protected virtual void BeginRun()
        {
            RunCanExecuteChanged();
            IsBusy = true;
            new Action(Run).BeginInvoke(RunCompletedInWorkerThread, null);
        }
        private void RunCompletedInWorkerThread(IAsyncResult result)
        {
            View.Dispatcher.Invoke(new Action<IAsyncResult>(RunCompleted), result);
        }
        protected virtual void RunCompleted(IAsyncResult result)
        {
            IsBusy = false;
            RunCanExecuteChanged();
        }
        #endregion
        protected virtual void Run()
        {
            View.Dispatcher.Invoke(new Action(Records.Clear));

            var configuration = Container.Resolve<IConfiguration>();

            var config = Configuration.Load(new LocalFileSystem(), Settings.Default.TestsFolder,"");
            var participants = Directory.GetDirectories(Folder, "*.*.*.*");
            if (participants != null)
            {
                var fs = new LocalFileSystem();
                foreach (var partFolder in participants)
                {
                    //configuration.SolutionsFolder = partFolder;

                    var participant = Participant.Load(fs,partFolder);


                    //var solutions = participant.Discover(configuration);

                    var record = new Record
                    {
                        Participant = participant,
                        //Solutions = solutions,
                        Folder = partFolder,
                        IsPending = true,
                    };
                    View.Dispatcher.Invoke(new Action<Record>(Records.Add), record);
                    

                    foreach (var solution in record.Participant.Solutions)
                    {
                        solution.FileSystem = fs;
                        record.IsPending = true;
                        solution.Configuration = config;

                        foreach (var devTool in config.DevTools)
                        {
                            if (solution.DevTool.Name == devTool.Name)
                            {
                                solution.DevTool = devTool;
                            }
                        }

                        solution.Check(LocalFolder, partFolder);
                        File.AppendAllText("log.txt", "solution " + solution.Task.Name + solution.Score);
                    }

                    record.IsPending = false;
                }
            }
        }

        protected virtual bool CanRun()
        {
            return !IsBusy && !string.IsNullOrEmpty(Folder);
        }

        #region Browse Command
        private DelegateCommand<object> _browseCommand;
        public ICommand BrowseCommand
        {
            get
            {
                if (_browseCommand == null)
                {
                    _browseCommand = new DelegateCommand<object>(x => Browse(), x => CanBrowse());
                }
                return _browseCommand;
            }
        }
        protected virtual void BrowseCanExecuteChanged()
        {
            if (_browseCommand != null)
            {
                _browseCommand.RaiseCanExecuteChanged();
            }
        }
        #endregion
        protected virtual void Browse()
        {
            using (var dialog = new FolderBrowserDialog())
            {
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    
                    Folder = dialog.SelectedPath;
                }
            }
            
        }
        protected virtual bool CanBrowse()
        {
            return !IsBusy;
        }

        #region Save Command
        private DelegateCommand<object> _saveCommand;
        public ICommand SaveCommand
        {
            get
            {
                if (_saveCommand == null)
                {
                    _saveCommand = new DelegateCommand<object>(x => Save(), x => CanSave());
                }
                return _saveCommand;
            }
        }
        protected virtual void SaveCanExecuteChanged()
        {
            if (_saveCommand != null)
            {
                _saveCommand.RaiseCanExecuteChanged();
            }
        }
        #endregion
        protected virtual void Save()
        {
            using (var dialog = new FolderBrowserDialog())
            {
                dialog.SelectedPath = Folder;
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    var folder = dialog.SelectedPath;

                    using (var file = File.Open(Path.Combine(folder,
                        string.Format("records_{0:t}.csv", DateTime.Now).Replace(':', '_')), FileMode.Create))
                    using (var writer = new StreamWriter(file,Encoding.GetEncoding(1251)))
                    {
                        writer.WriteLine("\"Папка\";\"Участник\";\"Школа\";\"Класс\";\"Балы\"");
                        foreach (var record in Records)
                        {
                            writer.WriteLine("\"{0}\";\"{1}\";\"{2} {3}\";\"{4}\";\"{5}\"", record.Folder,
                                record.FullName, record.Participant.School,
                                record.Participant.HomeTown,record.Participant.Grade,record.Score);
                        }

                        writer.Flush();
                        file.Flush();
                    }
                    using (var file = File.Open(Path.Combine(folder,
                        string.Format("solutions_{0:t}.csv", DateTime.Now).Replace(':', '_')), FileMode.Create))
                    using (var writer = new StreamWriter(file, Encoding.GetEncoding(1251)))
                    {
                        writer.WriteLine("\"Участник\";\"Задача\";\"Пройдено\";\"Балы\";\"Неверных решений\";\"Сбоев программы\"");
                        foreach (var record in Records)
                        {
                            foreach (var solution in record.Participant.Solutions)
                            {
                                writer.WriteLine("\"{0}\";\"{1}\";\"{2}\";\"{3}\";\"{4}\";\"{5}\"", record.FullName,
                                     solution.Name, solution.Score, solution.WeightedScore,
                                     solution.FailedChecks, solution.FailedRuns);
                            }
                        }
                        writer.Flush();
                        file.Flush();
                    }
                }
            }

        }
        protected virtual bool CanSave()
        {
            return !IsBusy;
        }



        ObservableCollection<Record> _records = new ObservableCollection<Record>();
        public ObservableCollection<Record> Records
        {
            get
            {
                return _records;
            }
        }

        const string IsPendingPropertyName = "IsPending";
        private bool _isPending;
        public bool IsPending
        {
            get { return _isPending; }
            set
            {
                if (_isPending != value)
                {
                    _isPending = value;
                    OnPropertyChanged(IsPendingPropertyName);
                }
            }
        }

        public static string LocalFolder
        {
            get
            {
                var folder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Tester");

                if (!Directory.Exists(folder))
                {
                    Directory.CreateDirectory(folder);
                }

                return folder;
            }
        }



    }
}
